package com.suredy.app.porject.ctrl;

import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.suredy.app.porject.constants.ContractOpLogType;
import com.suredy.app.porject.constants.ContractStatus;
import com.suredy.app.porject.constants.ContractType;
import com.suredy.app.porject.constants.FlowStatus;
import com.suredy.app.porject.constants.UserFileType;
import com.suredy.app.porject.ctrl.flow.FlowCtrl;
import com.suredy.app.porject.ctrl.flow.FlowCtrlForProject;
import com.suredy.app.porject.ctrl.view.ViewRoleCtrlForContract;
import com.suredy.app.porject.model.Contract;
import com.suredy.app.porject.model.ContractFile;
import com.suredy.app.porject.model.ContractMoney;
import com.suredy.app.porject.model.ContractOpLog;
import com.suredy.app.porject.model.ContractPayoutPlan;
import com.suredy.app.porject.model.vo.ContractPayoutPlanArray;
import com.suredy.app.porject.model.vo.MaterialContractEditModel;
import com.suredy.app.porject.model.vo.SubContractEditModel;
import com.suredy.app.porject.model.vo.TaskContractEditModel;
import com.suredy.app.porject.roles.SystemRoles;
import com.suredy.app.porject.service.ContractFileSrv;
import com.suredy.app.porject.service.ContractMoneySrv;
import com.suredy.app.porject.service.ContractOpLogSrv;
import com.suredy.app.porject.service.ContractPayoutPlanSrv;
import com.suredy.app.porject.service.ContractSrv;
import com.suredy.app.porject.service.FlowOfContract2UserSrv;
import com.suredy.app.porject.service.ProjectConstants;
import com.suredy.app.porject.tools.FileTool;
import com.suredy.core.helper.ApplicationContextHelper;
import com.suredy.core.model.BaseModel;
import com.suredy.core.mvc.model.MessageModel;
import com.suredy.security.entity.UserEntity;

/**
 * 子合同控制器
 * 
 * @author VIVID.G
 * @since 2015-10-15
 * @version v0.1
 */
@Controller
@RequestMapping("/sub-contract")
public class SubContractCtrl extends FlowCtrl {

	private final static Logger log = LoggerFactory.getLogger(SubContractCtrl.class);

	@Autowired
	private FileTool fileTool;

	@Autowired
	private ContractFileSrv contractFileSrv;

	@Autowired
	private ContractSrv contractSrv;

	@Autowired
	private ContractOpLogSrv contractOpLogSrv;

	@Autowired
	private ContractMoneySrv moneySrv;

	@Autowired
	private ContractPayoutPlanSrv contractPayoutPlanSrv;

	@Autowired
	private ProjectConstants constants;

	@RequestMapping(value = "/create/{pId}/{type}", method = RequestMethod.GET)
	public String doSubContractForm(@PathVariable String pId, @PathVariable ContractType type, Model model) {
		String view = "app/contract/contract-create-sub";

		if (StringUtils.isBlank(pId) || type == null) {
			model.addAttribute("invalid", true);
			return view;
		}

		Contract parent = this.contractSrv.get(pId);

		if (parent == null) {
			model.addAttribute("invalid", true);
			return view;
		}

		switch (type) {
			case TASK_CONTRACT:
				view = "app/contract/contract-create-task";
				model.addAttribute("companyB", this.constants.getDoContractCompany(null));
				break;
			case MATERIAL_CONTRACT:
				view = "app/contract/contract-create-material";
				break;
			case AGREEMENT_CONTRACT:
				view = "app/contract/contract-create-agreement";
				break;
		}

		model.addAttribute("parent", parent);
		model.addAttribute("type", type);
		model.addAttribute("jiesuanWay", this.constants.getContractJiesuanWay(null));

		return view;
	}

	@RequestMapping(value = "/create", method = RequestMethod.POST)
	@ResponseBody
	public Object doSubContract(Contract contract, @RequestParam(value = "contractFile", required = true) MultipartFile contractFile, @RequestParam(value = "file", required = false) MultipartFile[] file) {
		if (contract == null)
			return new MessageModel(false, "无效的合同信息！", null);

		if (contract.getParent() == null || StringUtils.isBlank(contract.getParent().getId()))
			return new MessageModel(false, "无效的主合同信息！", null);

		// 修复金额，便于保存信息
		if (contract.getMoney() != null) {
			for (ContractMoney m : contract.getMoney()) {
				m.setContract(contract);
			}
		}

		// 设置负责人（子合同谁建的谁负责）
		contract.setXiangmuHeader(new UserEntity(this.getUser().getId()));
		contract.setJijingHeader(new UserEntity(this.getUser().getId()));

		// 初始化流程
		this.createContractFlowInfo(contract, new UserEntity(this.getUser().getId()), FlowStatus.FS2000_CONTRACT_TO_CREATE);

		contract.setFlowStatus(FlowStatus.FS2002_CONTRACT_STARTED);

		contract.setCreateTime(new Date());

		contract = this.contractSrv.save(contract);

		if (contract == null || StringUtils.isBlank(contract.getId()))
			return new MessageModel(false, "保存合同信息失败！", null);

		// 完工后需要修改流程状态（模拟开始履行）
		FlowCtrlForProject flow = ApplicationContextHelper.getBeanByType(FlowCtrlForProject.class);
		flow.changeStatusForContract(contract.getId(), FlowStatus.FS2001_CONTRACT_CREATED);
		FlowOfContract2UserSrv fcus = ApplicationContextHelper.getBeanByType(FlowOfContract2UserSrv.class);
		fcus.sendWithUsers(contract.getId(), new String[] {this.getUser().getId()}, FlowStatus.FS2002_CONTRACT_STARTED);

		// 合同文件
		UserFileType uft = ContractType.AGREEMENT_CONTRACT.equals(contract.getType()) ? UserFileType.F202_CONTRACT_AGREEMENT_FILE : UserFileType.F200_CONTRACT_FILE;
		if (contractFile != null)
			this.saveFile(contractFile, contract.getId(), uft);

		// 保存文件
		if (file != null) {
			for (MultipartFile f : file) {
				this.saveFile(f, contract.getId(), UserFileType.Z900_OTHER);
			}
		}

		// 记录主合同操作日志
		ContractOpLogType colt = ContractType.AGREEMENT_CONTRACT.equals(contract.getType()) ? ContractOpLogType.CONTRACT_AGREEMENT : ContractOpLogType.SUB_CONTRACT;
		ContractOpLog log = this.recordOpLog(contract.getParent(), colt, "创建【" + contract.getType().getValue() + "】" + contract.getNo());
		if (log == null)
			return new MessageModel(false, "记录操作日志出错", null);
		this.contractOpLogSrv.save(log);

		return new MessageModel(true, "操作成功！", null);
	}

	@RequestMapping(value = "/view/{id}", method = RequestMethod.GET)
	public String subView(@PathVariable String id, Model model) {
		String view = "app/contract/contract-sub-view";

		if (StringUtils.isBlank(id))
			return view;

		Contract data = null;
		String pId = null;

		String ql = "SELECT T, T.parent.id FROM Contract T WHERE T.id=?";

		Object[] obj = (Object[]) this.contractSrv.readSingleByQL(ql, id);

		if (obj == null || obj.length != 2)
			data = null;
		else {
			data = (Contract) obj[0];
			pId = (String) obj[1];
		}

		if (data == null)
			return view;

		switch (data.getType()) {
			case TASK_CONTRACT:
				view = "app/contract/contract-sub-view-for-task";
				break;
			case MATERIAL_CONTRACT:
				view = "app/contract/contract-sub-view-for-material";
				break;
			case AGREEMENT_CONTRACT:
				view = "app/contract/contract-agreement-view";
				break;
		}

		model.addAttribute("data", data);
		model.addAttribute("pId", pId);
		model.addAttribute("roles", new ViewRoleCtrlForContract(data, this.getUser(), this.getRoleCodesFromSession()));

		return view;
	}

	@RequestMapping(value = "/view/{id}/{tab}", method = RequestMethod.GET)
	public String subView(@PathVariable String id, @PathVariable String tab, Model model) {
		model.addAttribute("tab", tab);

		return this.subView(id, model);
	}

	@RequestMapping(value = "/edit")
	public String editForm(String id, Model model) {
		String view = "app/contract/sub/contract-edit-task";

		if (StringUtils.isBlank(id)) {
			model.addAttribute("invalid", true);
			return view;
		}

		Contract sub = this.contractSrv.get(id);

		if (sub == null) {
			model.addAttribute("invalid", true);
			return view;
		}

		switch (sub.getType()) {
			case TASK_CONTRACT:
				view = "app/contract/sub/contract-edit-task";
				model.addAttribute("companyB", this.constants.getDoContractCompany(null));
				break;
			case MATERIAL_CONTRACT:
				view = "app/contract/sub/contract-edit-material";
				break;
			case SUB_SERVICE_CONTRACT:
			case SUB_PROFESSIONAL_CONTRACT:
				view = "app/contract/sub/contract-edit-sub";
				break;
			default:
				model.addAttribute("invalidType", true);
				return view;
		}

		model.addAttribute("data", sub);

		return view;
	}

	@RequestMapping(value = "/edit-task")
	@ResponseBody
	public Object editTask(TaskContractEditModel contract) {
		return this.doEdit(contract);
	}

	@RequestMapping(value = "/edit-material")
	@ResponseBody
	public Object editMaterial(MaterialContractEditModel contract) {
		return this.doEdit(contract);
	}

	@RequestMapping(value = "/edit-sub")
	@ResponseBody
	public Object editSub(SubContractEditModel contract) {
		return this.doEdit(contract);
	}

	@RequestMapping(value = "/pay-out/{id}/{pid}", method = RequestMethod.GET)
	public String payOutForm(@PathVariable String id, @PathVariable String pid, Model model) {
		String view = "app/contract/contract-sub-payout";

		if (StringUtils.isBlank(id) || StringUtils.isBlank(pid)) {
			model.addAttribute("invalid", true);
			return view;
		}

		Contract c = this.contractSrv.get(id);

		if (c == null) {
			model.addAttribute("invalid", true);
			return view;
		}

		model.addAttribute("c", c);
		model.addAttribute("pid", pid);

		return view;
	}

	@RequestMapping(value = "/pay-out", method = RequestMethod.POST)
	@ResponseBody
	public Object payOut(ContractMoney money) {
		if (money == null)
			return new MessageModel(false, "操作失败，无效的付款信息！", null);

		if (money.getContract() == null || StringUtils.isBlank(money.getContract().getId()))
			return new MessageModel(false, "操作失败，对应的合同信息无效！", null);

		if (money.getTotal() == null)
			return new MessageModel(false, "操作失败，【付款金额】不能为空！", null);

		if (StringUtils.isBlank(money.getSource()))
			return new MessageModel(false, "操作失败，【部门/单位】不能为空！", null);

		if (money.getTime() == null)
			return new MessageModel(false, "操作失败，【付款日期】不能为空！", null);

		money = this.moneySrv.save(money);

		if (money == null || StringUtils.isBlank(money.getId()))
			return new MessageModel(false, "保存付款信息失败！", null);

		// 记录日志
		ContractOpLog log = this.recordOpLog(money.getContract(), ContractOpLogType.CONTRACT_PAY_OUT, "向【" + money.getSource() + "】支付：" + this.numberFormat(money.getTotal()));
		if (log == null)
			return new MessageModel(false, "记录操作日志出错", null);
		this.contractOpLogSrv.save(log);

		return new MessageModel(true, "操作成功！", null);
	}

	@RequestMapping(value = "/upload-file/{id}/{pid}", method = RequestMethod.GET)
	public String uploadFileForm(@PathVariable String id, @PathVariable String pid, Model model) {
		String view = "app/contract/sub-contract-file-upload";

		if (StringUtils.isBlank(id)) {
			model.addAttribute("invalid", true);
			return view;
		}

		model.addAttribute("id", id);
		model.addAttribute("pid", pid);

		return view;
	}

	@RequestMapping(value = "/upload-file/{id}", method = RequestMethod.POST)
	@ResponseBody
	public Object uploadBidFile(@PathVariable String id, @RequestParam(value = "file", required = false) MultipartFile file) {
		if (file == null)
			return new MessageModel(false, "请选择需要上传的文件！", null);

		if (StringUtils.isBlank(id))
			return new MessageModel(false, "无效的合同信息！", null);

		if (!this.saveFile(file, id, UserFileType.F200_CONTRACT_FILE))
			return new MessageModel(false, "文件保存失败！", null);

		return new MessageModel(true, "操作成功！", null);
	}

	@RequestMapping(value = "/clearing-contract/{id}/{pid}", method = RequestMethod.GET)
	public String clearingContractForm(@PathVariable String id, @PathVariable String pid, Model model) {
		String view = "app/contract/sub-contract-clearing";

		if (StringUtils.isBlank(id)) {
			model.addAttribute("invalid", true);
			return view;
		}

		Contract c = this.contractSrv.get(id);

		if (c == null || StringUtils.isBlank(c.getId())) {
			model.addAttribute("invalid", true);
			return view;
		}

		model.addAttribute("c", c);
		model.addAttribute("pid", pid);

		return view;
	}

	@RequestMapping(value = "/clearing-contract/{id}", method = RequestMethod.POST)
	@ResponseBody
	public Object clearingContract(@PathVariable String id, double clearingPrice, @RequestParam(value = "file", required = false) MultipartFile file, String remark) {
		if (StringUtils.isBlank(id))
			return new MessageModel(false, "操作失败，无效的合同信息！", null);

		Contract c = this.contractSrv.get(id);

		if (c == null || StringUtils.isBlank(c.getId()))
			return new MessageModel(false, "操作失败，未找到对应的合同信息！", null);

		if (StringUtils.isBlank(remark))
			remark = "";

		// 记录日志
		this.recordOpLog(c, ContractOpLogType.COMPLETE_CONTRACT, remark + " 【结算金额】：" + this.numberFormat(clearingPrice));

		c.setStatus(ContractStatus.COMPLETED);
		c.setClearingPrice(clearingPrice);

		c = this.contractSrv.update(c);

		if (c == null || StringUtils.isBlank(c.getId()))
			return new MessageModel(false, "操作失败，保存信息失败！", null);

		// 完工后需要修改流程状态
		FlowCtrlForProject flow = ApplicationContextHelper.getBeanByType(FlowCtrlForProject.class);
		flow.changeStatusForContract(c.getId(), FlowStatus.FS2003_CONTRACT_COMPLETED);

		if (file != null)
			if (!this.saveFile(file, id, UserFileType.F202_CONTRACT_CLOSE_MONEY))
				return new MessageModel(false, "上传文件失败！", null);

		return new MessageModel(true, "操作成功！", null);
	}

	@RequestMapping(value = "/payout-plan/{id}/{pid}", method = RequestMethod.GET)
	public String payoutPlanForm(@PathVariable String id, @PathVariable String pid, Model model) {
		String view = "app/contract/sub-contract-payout-plan";

		if (StringUtils.isBlank(id) || StringUtils.isBlank(pid)) {
			model.addAttribute("invalid", true);
			return view;
		}

		Contract c = this.contractSrv.get(id);

		if (c == null) {
			model.addAttribute("invalid", true);
			return view;
		}

		List<?> header = null;
		ContractType type = c.getType();
		if (type != null) {
			switch (type) {
				case MATERIAL_CONTRACT:
					// 材料合同
					header = this.getUserByRoles(SystemRoles.r_zhuanze_caigou);
					break;
				case TASK_CONTRACT:
				case SUB_SERVICE_CONTRACT:
				case SUB_PROFESSIONAL_CONTRACT:
					// 统计专责
					header = this.getUserByRoles(SystemRoles.r_zhuanze_tongji);
					break;
				default:
					header = this.getUserByRoles(SystemRoles.r_people_money_out);
			}
		}

		model.addAttribute("cid", id);
		model.addAttribute("data", c);
		model.addAttribute("pid", pid);
		model.addAttribute("header", header);

		return view;
	}

	@RequestMapping(value = "/payout-plan", method = RequestMethod.POST)
	@ResponseBody
	public Object payoutPlan(ContractPayoutPlan plan) {
		if (plan == null)
			return new MessageModel(false, "无效的付款信息！", null);

		if (plan.getContract() == null || StringUtils.isBlank(plan.getContract().getId()))
			return new MessageModel(false, "未能找到对应的合同信息，无法记录付款情况！", null);

		if (StringUtils.isBlank(plan.getReason()) || plan.getTotal() == null || plan.getPayoutTime() == null)
			return new MessageModel(false, "【付款事项】、【付款金额】、【付款日期】不能为空！", null);

		if (plan.getCreateTime() == null)
			plan.setCreateTime(new Date());

		plan.setCreater(new UserEntity(this.getUser().getId()));

		plan = this.contractPayoutPlanSrv.save(plan);

		if (plan == null || StringUtils.isBlank(plan.getId()))
			return new MessageModel(false, "记录付款计划出错！", null);

		// 记录主合同操作日志
		ContractOpLog log = this.recordOpLog(plan.getContract(), ContractOpLogType.CONTRACT_PAY_OUT_PLAN, "金额：" + this.numberFormat(plan.getTotal()) + "（" + this.datetimeFormat(plan.getPayoutTime(), "yyyy-MM-dd") + "）");
		if (log == null)
			return new MessageModel(false, "记录操作日志出错", null);
		this.contractOpLogSrv.save(log);

		return new MessageModel(true, "操作成功！", null);
	}

	@RequestMapping(value = "/payout-plan-multiple/{id}/{pid}", method = RequestMethod.GET)
	public String payoutPlanMultipleForm(@PathVariable String id, @PathVariable String pid, Model model) {
		String view = "app/contract/sub-contract-payout-plan-multiple";

		if (StringUtils.isBlank(id) || StringUtils.isBlank(pid)) {
			model.addAttribute("invalid", true);
			return view;
		}

		Contract c = this.contractSrv.get(id);

		if (c == null) {
			model.addAttribute("invalid", true);
			return view;
		}

		List<?> header = null;
		ContractType type = c.getType();
		if (type != null) {
			switch (type) {
				case MATERIAL_CONTRACT:
					// 材料合同
					header = this.getUserByRoles(SystemRoles.r_zhuanze_caigou);
					break;
				case TASK_CONTRACT:
				case SUB_SERVICE_CONTRACT:
				case SUB_PROFESSIONAL_CONTRACT:
					// 统计专责
					header = this.getUserByRoles(SystemRoles.r_zhuanze_tongji);
					break;
				default:
					header = this.getUserByRoles(SystemRoles.r_people_money_out);
			}
		}

		model.addAttribute("cid", id);
		model.addAttribute("data", c);
		model.addAttribute("pid", pid);
		model.addAttribute("header", header);

		return view;
	}

	@RequestMapping(value = "/payout-plan-multiple", method = RequestMethod.POST)
	@ResponseBody
	public Object payoutPlanMultiple(ContractPayoutPlanArray plans) {
		if (plans == null || plans.getArray() == null || plans.getArray().isEmpty())
			return new MessageModel(false, "无效的付款信息！", null);

		for (ContractPayoutPlan plan : plans.getArray()) {
			if (plan.getContract() == null || StringUtils.isBlank(plan.getContract().getId()))
				continue;

			if (StringUtils.isBlank(plan.getReason()) || plan.getTotal() == null || plan.getPayoutTime() == null)
				continue;

			if (plan.getCreateTime() == null)
				plan.setCreateTime(new Date());

			plan.setCreater(new UserEntity(this.getUser().getId()));

			plan = this.contractPayoutPlanSrv.save(plan);

			if (plan == null || StringUtils.isBlank(plan.getId()))
				continue;

			// 记录主合同操作日志
			ContractOpLog log = this.recordOpLog(plan.getContract(), ContractOpLogType.CONTRACT_PAY_OUT_PLAN, "金额：" + this.numberFormat(plan.getTotal()) + "（" + this.datetimeFormat(plan.getPayoutTime(), "yyyy-MM-dd") + "）");
			if (log == null)
				return new MessageModel(false, "记录操作日志出错", null);
			this.contractOpLogSrv.save(log);
		}

		return new MessageModel(true, "操作成功！", null);
	}

	@RequestMapping(value = "/delete-payout-plan/{id}", method = RequestMethod.POST)
	@ResponseBody
	public Object deletePayoutPlan(@PathVariable String id) {
		if (StringUtils.isBlank(id))
			return new MessageModel(false, "无效的付款计划信息！", null);

		ContractPayoutPlan data = this.contractPayoutPlanSrv.get(id);

		if (data == null)
			return new MessageModel(false, "无法找到指定付款计划！", null);

		String contractId = null;
		if (data.getContract() != null)
			contractId = this.contractPayoutPlanSrv.getContractId(id);

		data = this.contractPayoutPlanSrv.delete(data);

		if (data == null)
			return new MessageModel(false, "删除付款计划失败！", null);

		// 将子合同的删除信息记录在父合同中
		if (!StringUtils.isBlank(contractId)) {
			Contract parent = new Contract();
			parent.setId(contractId);

			String remark = data.getReason();
			remark += "[" + this.numberFormat(data.getTotal()) + "]";
			remark += " 计划付款时间：" + this.datetimeFormat(data.getPayoutTime(), "yyyy-MM-dd");

			// 记录日志
			ContractOpLog log = this.recordOpLog(parent, ContractOpLogType.CONTRACT_PAYOUT_PLAN_DELETE, remark);

			this.contractOpLogSrv.save(log);
		}

		return new MessageModel(true, "操作成功！", null);
	}

	@RequestMapping(value = "/payout-plan-change/{id}", method = RequestMethod.GET)
	public String changePayoutPlanForm(@PathVariable String id, Model model) {
		String view = "app/contract/sub-contract-payout-plan-change";

		if (StringUtils.isBlank(id)) {
			model.addAttribute("invalid", true);
			return view;
		}

		String ql = "SELECT T, T.contract.id, T.contract.type FROM ContractPayoutPlan T WHERE T.id=?";

		Object[] obj = (Object[]) this.contractPayoutPlanSrv.readSingleByQL(ql, id);

		if (obj == null) {
			model.addAttribute("invalid", true);
			return view;
		}

		ContractPayoutPlan data = (ContractPayoutPlan) obj[0];
		String contractId = (String) obj[1];
		ContractType type = (ContractType) obj[2];

		List<?> header = null;
		if (type != null) {
			switch (type) {
				case MATERIAL_CONTRACT:
					// 材料合同
					header = this.getUserByRoles(SystemRoles.r_zhuanze_caigou);
					break;
				case TASK_CONTRACT:
				case SUB_SERVICE_CONTRACT:
				case SUB_PROFESSIONAL_CONTRACT:
					// 统计专责
					header = this.getUserByRoles(SystemRoles.r_zhuanze_tongji);
					break;
				default:
					header = this.getUserByRoles(SystemRoles.r_people_money_out);
			}
		}

		model.addAttribute("data", data);
		model.addAttribute("cid", contractId);
		model.addAttribute("header", header);

		return view;
	}

	@RequestMapping(value = "/payout-plan-change", method = RequestMethod.POST)
	@ResponseBody
	public Object changePayoutPlan(ContractPayoutPlan plan) {
		if (plan == null || StringUtils.isBlank(plan.getId()) || plan.getContract() == null || StringUtils.isBlank(plan.getContract().getId()))
			return MessageModel.createErrorMessage("无效的付款计划！", null);

		if (StringUtils.isBlank(plan.getChangeReason()))
			return MessageModel.createErrorMessage("请正确填写变更原因！", null);

		ContractPayoutPlan data = this.contractPayoutPlanSrv.get(plan.getId());

		if (data == null)
			return MessageModel.createErrorMessage("未找到需要变更的付款计划信息！", null);

		String newReason = plan.getChangeReason();

		plan.setChangeReason(this.makeChangeReasonString(data.getChangeReason(), newReason));

		String contractId = plan.getContract().getId();

		plan = this.contractPayoutPlanSrv.update(plan);

		if (plan == null)
			return MessageModel.createErrorMessage("变更工期计划失败！", null);

		// 记录主合同操作日志
		Contract c = new Contract();
		c.setId(contractId);
		ContractOpLog log = this.recordOpLog(c, ContractOpLogType.CONTRACT_PAY_OUT_PLAN_CHANGE, newReason);
		if (log == null)
			return new MessageModel(false, "记录操作日志出错", null);
		this.contractOpLogSrv.save(log);

		return new MessageModel(true, "操作成功！", null);
	}

	private boolean saveFile(MultipartFile file, String contractId, UserFileType type) {
		if (StringUtils.isBlank(contractId))
			return false;

		if (type == null)
			type = UserFileType.Z900_OTHER;

		Contract c = new Contract();
		c.setId(contractId);

		String fileName = file.getOriginalFilename();

		String suffix = fileName.substring(fileName.lastIndexOf('.'));
		fileName = fileName.substring(0, fileName.lastIndexOf('.'));

		try {
			File tmp = this.fileTool.store(file.getInputStream(), contractId);

			ContractFile data = new ContractFile();

			data.setType(type);
			data.setContract(c);
			data.setFileName(fileName);
			data.setFilePath(this.fileTool.relativelyPath(tmp));
			data.setSize(file.getSize());
			data.setSuffix(suffix);
			data.setUploadTime(new Date());
			data.setUserName(this.getUser().getName());

			data = this.contractFileSrv.save(data);

			return data != null && !StringUtils.isBlank(data.getId());
		} catch (IOException e) {
			log.error("Receive file error", e);
		}

		return false;
	}

	/**
	 * 新建操作日志
	 * 
	 * @param op
	 * @param remark
	 * @return
	 */
	private ContractOpLog newOpLog(ContractOpLogType op, String remark) {
		if (op == null)
			return null;

		ContractOpLog log = new ContractOpLog();

		log.setTime(new Date());
		log.setOp(op);
		log.setOper(this.getUser().getName());
		log.setRemark(remark);

		return log;
	}

	/**
	 * 记录操作日志
	 * 
	 * @param c
	 * @param op
	 * @param remark
	 */
	private ContractOpLog recordOpLog(Contract c, ContractOpLogType op, String remark) {
		if (c == null)
			return null;

		ContractOpLog log = this.newOpLog(op, remark);

		if (log == null)
			return null;

		if (c.getOpLog() == null)
			c.setOpLog(new ArrayList<ContractOpLog>());

		log.setContract(c);

		c.getOpLog().add(log);

		return log;
	}

	private String numberFormat(double number) {
		NumberFormat nf = new DecimalFormat("￥#,###.00");

		return nf.format(number);
	}

	private String datetimeFormat(Date d, String pattern) {
		if (d == null)
			return "";

		SimpleDateFormat sdf = new SimpleDateFormat(pattern);

		return sdf.format(d);
	}

	/**
	 * 构建工期计划变更信息的字符串
	 * 
	 * @param old
	 * @param now
	 * @return
	 */
	private String makeChangeReasonString(String old, String now) {
		old = StringUtils.isBlank(old) ? "" : old + "++--++";

		return old + this.datetimeFormat(new Date(), "yyyy-MM-dd HH:mm:ss") + "--++--" + this.getUser().getName() + "--++--" + now;
	}

	public Object doEdit(BaseModel model) {
		if (model == null || StringUtils.isBlank(model.getId()))
			return MessageModel.createErrorMessage("合同信息无效！", null);

		Contract sub = this.contractSrv.get(model.getId());

		if (sub == null)
			return MessageModel.createErrorMessage("无法找到对应的合同信息，更新失败！", null);

		try {
			PropertyUtils.copyProperties(sub, model);
		} catch (Exception e) {
			return MessageModel.createErrorMessage("更新信息失败！", null);
		}

		sub = this.contractSrv.update(sub);

		if (sub == null)
			return MessageModel.createErrorMessage("更新信息失败！", null);

		return MessageModel.createSuccessMessage("操作成功", null);
	}

}
